package xyz.labmem.core.reflex

import cn.hutool.core.date.DateUtil
import cn.hutool.core.util.ClassUtil
import cn.hutool.log.StaticLog
import javafx.application.Application
import javafx.application.Platform
import javafx.stage.Stage
import kotlinx.coroutines.DelicateCoroutinesApi
import xyz.labmem.core.annotation.FXAspect
import xyz.labmem.core.annotation.FXController
import xyz.labmem.core.annotation.FXLoadController
import xyz.labmem.core.annotation.LabFXApplication
import xyz.labmem.core.base.BaseController
import xyz.labmem.core.context.FXApplicationContext
import xyz.labmem.core.exception.LabFatalException
import kotlin.system.exitProcess


/**
 * 启动程序
 * @Author lty
 * @Date 2021/9/14 16:06
 */
class FXApplication {

    companion object {

        fun close(closeBefore: (() -> Unit)?) {
            closeBefore?.let { it() }
            StaticLog.info(">>>>>LabFXApp--完全关闭")
            Platform.exit()
            exitProcess(0)
        }

        fun close() = close { }

        /**
         * 运行初始化
         */
        fun <T : Application> run(mainClass: Class<T>, args: Array<String>) {
            StaticLog.info("----启动LAB-FXApp----")
            //扫描controller class
            scanController(mainClass)
            //启动JavaFx
            Application.launch(mainClass, *args)
        }

        /**
         * 启动
         */
        @OptIn(DelicateCoroutinesApi::class)
        fun start(primaryStage: Stage, application: Application) {
            val timer = DateUtil.timer()
            //启动Main窗口
            FXApplicationContext.application = application
            if (FXApplicationContext.mainControllerClazz != null) {
                FXBuilder.startStage(primaryStage, FXApplicationContext.mainControllerClazz!!)
            } else
                throw LabFatalException("未找到MainController")
            StaticLog.info("----启动完成---- 启动时长：${timer.interval()}毫秒")
        }

        /**
         * 扫描controller
         */
        private fun <T : Application> scanController(mainClass: Class<T>) {
            val app = mainClass.getAnnotation(LabFXApplication::class.java)
            val bases = ArrayList<String>()
            FXApplicationContext.onlyApp = app.onlyApp
            if (app.base.isNotEmpty()) {
                bases.addAll(app.base)
            } else {
                bases.add(mainClass.packageName)
            }
            for (pack in bases) {
                val clazz = ClassUtil.scanPackage(pack)
                for (c in clazz) {
                    val contr = c.getAnnotation(FXController::class.java)
                    if (contr != null) {
                        FXApplicationContext.controllerClazz[c.simpleName] = c as Class<BaseController>
                        if (contr.main) {
                            if (FXApplicationContext.mainControllerClazz != null)
                                StaticLog.warn("扫描到多个mainController！")
                            FXApplicationContext.mainControllerClazz = c
                        }
                        val loadContr = c.getAnnotation(FXLoadController::class.java)
                        if (loadContr != null)
                            FXApplicationContext.loadControllerClazz[c.simpleName] = c
                        //获取切面并实例化储存
                        val fxAspect = c.getAnnotation(FXAspect::class.java)
                        if (fxAspect != null) {
                            FXApplicationContext.aspectBeans[c.simpleName] =
                                fxAspect.aspectClazz.java.getDeclaredConstructor().newInstance()
                        }
                    }
                }
            }
        }

    }


}